#include "Threading.h"
#include <process.h>
#include <ctime>
#include <Windows.h>
#include <iostream>
#include <fstream>
using namespace std;

#define NUMBEROFCLIENTS 1

int main()
{ 
	/** Creating multiple objects **/
	WindowsThreading *Obj = new WindowsThreading[NUMBEROFCLIENTS];
	
	/** setting the values **/
	Obj->SetNumberOfThreads(1);
	Obj->SetRowsMatrixA(100);
	Obj->SetColumsMatrixA(100);
	Obj->SetRowsMatrixB(100);
	Obj->SetColumsMatrixB(100);
	
	/** creating data structure for threading **/
	DataForThreadFunc *data_for_thread_func = new DataForThreadFunc[Obj->GetNumberOfThreads()]; //object=number of threads
	for(int i=0; i<Obj->GetNumberOfThreads(); i++)
	{
		data_for_thread_func[i].current_object = Obj;	//assigning same object address to all data structure
		data_for_thread_func[i].thread_number = 0;		//intializing
	}
	/** Dynamically Assigning memory **/
	Obj->AssignMemory(MATRIXA);
	Obj->AssignMemory(MATRIXB);
	Obj->AssignMemory(MATRIXC);
	Obj->AssignMemory(MATRIXBTRANSPOSE);

	/** Setting Matrix A and B with Random values **/
	Obj->MatrixGeneration(MATRIXA);
	Obj->MatrixGeneration(MATRIXB);

	if(Obj->GetColumsMatrixA()!=Obj->GetRowsMatrixB())
	{
		cout<<"multiplication not possible"<<endl;
		return 0;
	}
	time_t start, end, diff;
	cout<<"Start\n";

	/** creating dynamic thread array **/
	HANDLE* thread_array;
	thread_array = new HANDLE[Obj->GetNumberOfThreads()];
	
	/** starting threads **/
	start = clock();
	
	Obj->MatrixTranspose(); //B transpose
	
	for(int i=0; i<Obj->GetNumberOfThreads(); i++)
	{	
		data_for_thread_func[i].thread_number = i;
		thread_array[i] = (HANDLE)_beginthread(ThreadFunction,0,(void*)&data_for_thread_func[i]);
	}
	for (int i=0; i<Obj->GetNumberOfThreads(); i++)
		WaitForSingleObject(thread_array[i], INFINITE);
	end = clock();
	diff = end - start;
	cout << "Time taken =  "<< diff << "ms"<<endl;
	cout<<endl<<"Multiplication done"<<endl;
	
	/** Storing in files **/
	Obj->MatrixStore(MATRIXA);
	Obj->MatrixStore(MATRIXB);
	Obj->MatrixStore(MATRIXC);
	Obj->MatrixStore(MATRIXBTRANSPOSE);
	
	/** Deleting memory **/
	Obj->DeleteMemory(MATRIXA);
	Obj->DeleteMemory(MATRIXB);
	Obj->DeleteMemory(MATRIXC);
	Obj->DeleteMemory(MATRIXBTRANSPOSE);
	delete thread_array;

	return 0;
}